package com.ruoyi.common.utils.weixin;

import java.security.MessageDigest;
import java.util.*;

import com.ruoyi.common.utils.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.WxConstants;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.weixin.po.AccessToken;
import com.ruoyi.common.utils.weixin.po.AccessUser;

public class WeixinUtil {

    public static Map<String, String> map;

    private static Log logger = LogFactory.getLog(WeixinUtil.class);

    // 根据授权获取的code得到openid
    public final static String access_openid_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=APPSECRET&code=CODE&grant_type=authorization_code";

    // 获取access_token的接口地址（GET） 限200（次/天）
    public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token";
    // ?grant_type=client_credential&appid=APPID&secret=APPSECRET

    // 获取access_ticket的接口地址（GET） 限200（次/天）
    public final static String access_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

    // 获取所有关注用户列表
    public final static String access_users_url = "https://api.weixin.qq.com/cgi-bin/user/get";
    // ?access_token=ACCESS_TOKEN

    // 获取所有用户详细信息
    public final static String access_users_detail_url = "https://api.weixin.qq.com/cgi-bin/user/info";
    // ?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

    // 发送用户客服信息
    public final static String send_user_msg_url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=";
    // https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=

    // 我自己公众号的
    public final static String token_me = "dhqwx";
    // 我自己测试公众号的
    public final static String token_cs = "dhq_cs";

    // xiaobeikoudai
    public final static String token_xiaobeikoudai = "xiaobeikoudai";
    // xiaobeilaihua
    public final static String token_xiaobeilaihua = "xiaobeilaihua";

    /**
     * 验证token
     * @param signature
     * @param timestamp
     * @param nonce
     * @return
     */
    public static boolean checkSingature(String token, String signature,String timestamp,String nonce) {
        // String[] arr = new String[] {token_me,timestamp,nonce};

        String[] arr = new String[] {token,timestamp,nonce};
        // 数组排序
        Arrays.sort(arr);
        // 生成字符串
        StringBuffer content = new StringBuffer();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        // sha1 加密
        String temp  = getSha1(content.toString());
        // 与传输过来的相互比较
        return temp.equals(signature);
    }

    /*  token 验证 */
    public static Boolean verifyInfo(String signature, String timestamp, String nonce, String token) {
        TreeSet<String> set = new TreeSet<String>();
        set.add(token);
        set.add(timestamp);
        set.add(nonce);
        StringBuilder sBuilder = new StringBuilder();
        for (String item : set) {
            sBuilder.append(item);
        }
        String sign = getSha1(sBuilder.toString());
        return signature.equalsIgnoreCase(sign);
    }


    // sha1 加密算法
    public static String getSha1(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));

            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            return null;
        }
    }



    /**
     * 获取access_token
     *
     * @param appid     凭证
     * @param appsecret 密钥
     * @return
     */
    public static AccessToken getAccessToken(String appid, String appsecret) {
        //String token = "";
        String param = "grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
        String jsonStr = HttpUtils.sendGet(access_token_url, param);
        //logger.debug(jsonStr);

        JSONObject object = JSONObject.parseObject(jsonStr);
        // 如果请求成功
        AccessToken  accessToken = new AccessToken();
        if(StringUtils.isNotEmpty(object.getString("errcode"))){// 请求失败
            accessToken.setErrcode(object.getInteger("errcode"));
            accessToken.setErrmsg(object.getString("errmsg"));
        }
        accessToken.setToken(object.getString("access_token"));
        accessToken.setExpiresIn(object.getIntValue("expires_in"));

        return accessToken;
    }

    /**
     * 获取关注用户列表
     *
     * @param ACCESS_TOKEN
     * @return
     */
    public static List<AccessUser> getAccessUsers(String ACCESS_TOKEN) {
        List<AccessUser> accessUsers = new ArrayList<>();
        String param = "access_token=" + ACCESS_TOKEN;
        String jsonStr = HttpUtils.sendGet(access_users_url, param);
        JSONObject object = JSONObject.parseObject(jsonStr);
        // 如果请求成功
        if (null != object) {
            try {
                JSONObject data = (JSONObject) object.get("data");
                if (data != null) {
                    JSONArray openids = JSONObject.parseArray(data.getString("openid"));
                    if (openids.size() > 0) {
                        // 提取出openids中的所有 openid
                        for (int i = 0; i < openids.size(); i++) {
                            AccessUser accessUser = new AccessUser();
                            String openid = (String) openids.get(i);
                            accessUser.setOpenid(openid);
                            accessUsers.add(accessUser);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                // 获取ticket失败
                logger.info("获取AccessUsers失败 ");
            }
        }
        return accessUsers;
    }

    /**
     * 获取关注用户信息
     *
     * @param ACCESS_TOKEN
     * @return
     */
    public static JSONObject getAccessUser(String ACCESS_TOKEN, String OPENID) {
        String param = "access_token=" + ACCESS_TOKEN + "&openid=" + OPENID + "&lang=zh_CN";
        String jsonStr = HttpUtils.sendGet(access_users_detail_url, param);
        return JSONObject.parseObject(jsonStr);
    }

    /**
     * 发送客服消息
     *
     * @param accessToken
     * @param jsonMsg
     * @return errorCode
     */
    public static Integer sendCustomMessage(String accessToken, String jsonMsg) {
        String send_msg = send_user_msg_url + accessToken;
        // 发送客服消息
        JSONObject jsonObject = HttpUtils.httpRequest(send_msg, "POST", jsonMsg);

        logger.debug("jsonMsg " + jsonMsg);

        int errorCode = jsonObject.getIntValue("errcode");
        String errorMsg = jsonObject.getString("errmsg");
        logger.debug("发送客服消息返回  code ===> " + errorCode + "  msg ===> " + errorMsg);

        return errorCode;
    }

    public static String JsonTokfMsg(int type,String jsonStr, String openId) {
        String returnMsg = "";
        JSONObject str = JSONObject.parseObject(jsonStr);
        if(type == 1){
            String productName = str.getString("productName");
            String productUrl = str.getString("productUrl");
            returnMsg = "{ \"touser\" : " + " \""+ openId +"\" " + ","+
                    " \"msgtype\" : " + " \"text\" ," +
                    " \"text\" :{ " +
                        " \"content\" : " + "\"<a href='"+ productUrl +"'>"+productName+"</a>\" }" +
                    "}";
        }else {
            String topName = str.getString("topName");
            String productOneName = str.getString("productOneName");
            String productOneLink = str.getString("productOneLink");
            String productOneLinkText = str.getString("productOneLinkText");
            String productTwoName = str.getString("productTwoName");
            String productTwoLink = str.getString("productTwoLink");
            String productTwoLinkText = str.getString("productTwoLinkText");
            String endName = str.getString("endName");

            returnMsg = "{\"touser\":\"" + openId + "\",\"msgtype\":\"text\",\"text\":{\r\n" + " \"content\": \" " + topName
                    + " \r\r" + "【" + productOneName + "】  <a href='" + productOneLink + "'>"+productOneLinkText+"</a>\r";
            if (StringUtils.isNotEmpty(productTwoName) && StringUtils.isNotEmpty(productTwoLink))
                returnMsg += "【" + productTwoName + "】  <a href='" + productTwoLink + "'>"+productTwoLinkText+"</a>\r\r";

            else returnMsg += "\r";
            returnMsg += endName + " \r\"}}";
        }

        return returnMsg;
    }

    public static String ErrCodeConvertErrMsg(int errCode) {

        String errMsg = "";
        switch (errCode){
            case WxConstants.ERRCODE_01:
                errMsg = "未设置白名单";
                break;
            case WxConstants.ERRCODE_02:
                errMsg = "账户封停";
                break;
            case WxConstants.ERRCODE_03:
                errMsg = "无效的appId";
                break;
        }
        return  errMsg;
    }

    public static void main(String[] args) {
        AccessToken accessToken = getAccessToken(WxConstants.APPID_IN_SERVICE_3, WxConstants.APPSECRET_IN_SERVICE_3);
        System.err.println(accessToken.getToken());
    }
}
